package fr.jade.util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.AttributeController;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.fractal.api.control.ContentController;
import org.objectweb.fractal.api.control.LifeCycleController;
import org.objectweb.fractal.api.control.NameController;
import org.objectweb.fractal.api.control.SuperController;
import org.objectweb.fractal.api.factory.Factory;
import org.objectweb.fractal.api.factory.GenericFactory;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.api.type.InterfaceType;
import org.objectweb.fractal.api.type.TypeFactory;

import fr.jade.base.JadeBaseObject;
import fr.jade.fraclite.api.control.GenericAttributeController;
import fr.jade.fraclite.api.control.NoSuchAttributeException;
import fr.jade.fraclite.api.control.SuperControllerNotifier;
import fr.jade.service.fm.probe.ping.PingController;
import fr.jade.util.log.Logger;

/**
 * Provides static methods to access extended interfaces of Fractal components.
 */

public class FractalUtil extends JadeBaseObject{

  /**
   * Returns a bootstrap component to create other components. This method just
   * calls the corresponding method of the
   * <tt>org.objectweb.fractal.api.Fractal</tt> class.
   * 
   * @return a bootstrap component to create other components.
   * @throws InstantiationException
   *           if the bootstrap component cannot be created.
   */

  public static Component getBootstrapComponent() throws InstantiationException {
    return org.objectweb.fractal.util.Fractal.getBootstrapComponent();
  }

  /**
   * Returns the {@link AttributeController} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link AttributeController} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static GenericAttributeController getAttributeController(final Component component) throws NoSuchInterfaceException {
    return (GenericAttributeController) component.getFcInterface("generic-attribute-controller");
  }

  /**
   * Returns the {@link BindingController} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link BindingController} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static BindingController getBindingController(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getBindingController(component);
  }

  /**
   * Returns the {@link ContentController} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link ContentController} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static ContentController getOptContentController(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getContentController(component);
  }

  public static ContentController getContentController(final Component component) {
    try {
      return getOptContentController(component);
    } catch (NoSuchInterfaceException e) {
      throw new AssertionError("Component must have a content-controller interface");
    }
  }
  
  /**
   * Returns the {@link SuperController} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link SuperController} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static SuperController getOptSuperController(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getSuperController(component);
  }
  
  public static SuperController getSuperController(final Component component){
    try{
      return getOptSuperController(component);
    }catch(NoSuchInterfaceException e){
      throw new AssertionError("Component must have a super-controller interface");
    }
  }

  /**
   * Returns the {@link NameController} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link NameController} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static NameController getNameController(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getNameController(component);
  }

  /**
   * Returns the PingController interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the PingController interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static PingController getPingController(final Component component) throws NoSuchInterfaceException {
    return (PingController) component.getFcInterface("ping-controller");
  }

  public static SuperControllerNotifier getFcSuperControllerNotifier (final Component c) throws NoSuchInterfaceException{
      return (SuperControllerNotifier)c.getFcInterface("super-controller");
    }
  
  /**
   * Returns the {@link LifeCycleController} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link LifeCycleController} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static LifeCycleController getOptLifeCycleController(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getLifeCycleController(component);
  }
  
  public static LifeCycleController getLifeCycleController(final Component component) {
    try{
      return org.objectweb.fractal.util.Fractal.getLifeCycleController(component);
    }catch(NoSuchInterfaceException ignored){
      throw new AssertionError("Component must have a lifecycle-controller interface");
    }
  }

  /**
   * Returns the {@link Factory} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link Factory} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static Factory getFactory(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getFactory(component);
  }

  /**
   * Returns the {@link GenericFactory} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link GenericFactory} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static GenericFactory getGenericFactory(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getGenericFactory(component);
  }

  /**
   * Returns the {@link TypeFactory} interface of the given component.
   * 
   * @param component
   *          a component.
   * @return the {@link TypeFactory} interface of the given component.
   * @throws NoSuchInterfaceException
   *           if there is no such interface.
   */

  public static TypeFactory getTypeFactory(final Component component) throws NoSuchInterfaceException {
    return org.objectweb.fractal.util.Fractal.getTypeFactory(component);
  }

}
